<?php
/**
 * Created by PhpStorm.
 * Script Name: Mpmaterial.php
 * Create: 2023/1/3 14:03
 * Description:
 * Author: fudaoji<fdj@kuryun.cn>
 */

namespace plugin\wechat\app\tenant\controller;

use app\common\model\MediaFile;
use app\common\model\MediaImage;
use app\common\model\MediaVideo;
use app\common\model\MediaVoice;
use app\common\model\TenantApp;
use app\common\service\Media as MediaService;
use app\common\service\Tenant as TenantService;
use app\common\service\Upload;
use plugin\wechat\app\service\Mp as MpService;
use plugin\wechat\app\TenantController;
use support\View;
use think\facade\Db;
use Support\Request;
use plugin\wechat\app\model\MpMaterial as MaterialM;

class Mpmaterial extends TenantController
{
    /**
     * @var MaterialM
     */
    protected $model;
    /**
     * @var Upload
     */
    private Upload $uploadService;

    public function __construct()
    {
        parent::__construct();
        $this->model = new MaterialM();
        View::assign('config', dao_config('system.upload'));
        $this->uploadService = new Upload(dao_config('system.upload'));
    }

    /**
     * 弹框选择素材
     * @param Request $request
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * Author: fudaoji<fdj@kuryun.cn>
     */
    public function choose(Request $request){
        $mp_info = $request->mpInfo;
        $type = input('type', MediaService::IMAGE);
        $search_key = input('search_key', '');
        $where = [
            $this->tenantWhere(),
            ['mp_id', '=', $mp_info['id']],
            ['type', '=', $type]
        ];

        $search_key && $where[] = ['title', 'like', '%'.$search_key.'%'];
        if($type != MediaService::APP){
            $query = $this->model->where($where);
            $type == MediaService::NEWS && $query = $query->where('pid', 0);
            $data_list = $query->order('id', 'desc')
                ->paginate($this->pageSize);
        }else{
            $data_list = TenantApp::alias('ta')
                ->join('app app', 'app.name=ta.app_name')
                ->where([$this->tenantWhere(), ['ta.status','=', 1], ['ta.deadline','>', time()], ['app.status','=', 1]])
                ->order('ta.id', 'desc')
                ->field(['app.*'])
                ->paginate($this->pageSize);
        }

        $pager = $data_list->appends(['type' => $type, 'search_key' => $search_key])->render();
        if($type == MediaService::NEWS){
            foreach ($data_list as $k => $v){
                $where[] = ['pid', '=', $v['id']];
                $v['child'] = $this->model->where($where)
                    ->order('index',  'asc')
                    ->field(['thumb_url', 'title'])
                    ->select();
                $data_list[$k] = $v;
            }
        }
        $assign = [
            'data_list' => $data_list,
            'type' => $type,
            'pager' => $pager,
            'config' => dao_config('system.upload'),
            'field' => input('field', '') //目标input框
        ];
        return $this->show($assign, $type);
    }

    /**
     * 新增图文素材
     * @param Request $request
     * @return mixed|\support\Response
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \GuzzleHttp\Exception\GuzzleException
     * Author: fudaoji<fdj@kuryun.cn>
     */
    public function newsAdd(Request $request){
        $mp_info = $request->mpInfo;
        if(request()->isPost()){
            $post_data = input('post.');

            $news_list = $post_data['news_list'];
            if(count($news_list) < 1){
                return $this->error('请至少填写一条图文', '', ['token' => token()]);
            }
            $pid = 0;
            $list = [];
            Db::startTrans();
            try {
                $is_update = 0;
                foreach ($news_list as $key => $item){
                    unset($item['selected'], $item['top']);
                    $item['company_id'] = TenantService::getCompanyId();
                    $item['mp_id'] = $mp_info['id'];
                    $valid = $this->validate($item, '\\plugin\\wechat\\app\\validate\\MaterialNews.add');
                    if($valid !== true){
                        return $this->error($valid, '', ['token' => token()]);
                    }

                    if(!empty($item['id'])){ //编辑
                        $is_update = true;
                        $this->model->update($item);
                        $res = $item;
                    }else{ //新增
                        $item['pid'] = $pid;
                        $item['index'] = $key;
                        $res = $this->model->createOne($item);
                    }
                    array_push($list, $res);
                    $key === 0 && $pid = $res['id'];
                }
                $head = $list[0];
                //上传至微信素材库
                $params = ['type' => MediaService::NEWS, 'update' => $is_update, 'news_list' => $list];
                $is_update && $params['media_id'] = $head['media_id'];
                if(is_string($res = MpService::materialUpload($params))){
                    return $this->error($res, '', ['token' => token()]);
                }
                !$is_update && $this->model->update(['id' => $head['id'], 'media_id' => $res['media_id']]);
                Db::commit();
                return $this->success('操作成功!', url('index', ['type' => 'news']));
            }catch (\Exception $e) {
                $msg = is_string($e->getMessage()) ? $e->getMessage() : json_encode($e->getMessage(), JSON_UNESCAPED_UNICODE);
                dao_log()->error($msg);
                Db::rollback();
                return $this->error('操作失败:' . $msg, '', ['token' => token()]);
            }
        }

        $list = [];
        if($id = input('id', 0)){
            $list = $this->model->where([$this->tenantWhere(), ['id|pid', '=', $id]])
                ->order('index',  'asc')
                ->select();
            foreach ($list as $k => $v){
                $v['selected'] = $k == 0 ? 1 : 0;
                $list[$k] = $v;
            }
        }
        $assign = [
            'list'  => $list
        ];
        return $this->show($assign);
    }

    private function getModel($type = 'image'){
        $list = [
            MediaService::IMAGE => new MediaImage(),
            MediaService::VOICE => new MediaVoice(),
            MediaService::FILE => new MediaFile(),
            MediaService::VIDEO => new MediaVideo(),
        ];
        return isset($list[$type]) ? $list[$type] : null;
    }

    /**
     * 删除素材
     * @return \support\Response
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \GuzzleHttp\Exception\GuzzleException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * Author: fudaoji<fdj@kuryun.cn>
     */
    public function delPost(){
        $post_data = input();
        $ids = $post_data['ids'];
        foreach ($ids as $id){
            $data = $this->model->where([$this->tenantWhere()])->find($id);
            if($this->model->where([$this->tenantWhere(), ['id|pid','=', $id]])->delete()){
                in_array($data['type'], [MediaService::VIDEO, MediaService::VOICE, MediaService::IMAGE])
                && MpService::materialDel(['media_id' => $data['media_id']]); //删除永久素材
            }
        }
        return $this->success('操作成功!');
    }

    /**
     * 素材上传
     * Author: fudaoji<fdj@kuryun.cn>
     * @param Request $request
     * @return \support\Response
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function uploadPost(Request $request){
        if(request()->isPost()) {
            $post_data = input('');
            $mp_info = $request->mpInfo;
            foreach (request()->file() as $key => $file) {
                if(! $file->isValid()){
                    return $this->error('文件非法：' . $file->getUploadErrorCode());
                }
                /**
                 * 图片（image）: 10M，支持bmp/png/jpeg/jpg/gif格式
                语音（voice）：2M，播放长度不超过60s，mp3/wma/wav/amr格式
                视频（video）：10MB，支持MP4格式
                缩略图（thumb）：64KB，支持 JPG 格式
                 */
                $size = $file->getSize()/1000000;
                $limits = [MediaService::IMAGE => 10, MediaService::VIDEO => 10, MediaService::VOICE => 2];
                if($size > $limits[$post_data['type']]){
                    return $this->error('素材大小超过限制!');
                }

                //上传服务器
                $res = $this->uploadService->upload([$file], Upload::config($post_data['type']), ['uid' => 'tenant_'.$this->tenantInfo('id')]);
                if($res['code']){
                    $item = $res['data'][0];
                    $insert_data = [
                        'company_id' => TenantService::getCompanyId(),
                        'title' => $item['original_name'],
                        'url' => $item['url'],
                        'size' => $item['size'],
                        'ext' => $item['ext']
                    ];
                    $this->getModel($post_data['type'])->create($insert_data);

                    //上传微信
                    $dest_name = $file->getRealPath() . '.' . $file->getUploadName();
                    $file->move($dest_name);
                    $params = ['type' => $post_data['type'], 'path' => $dest_name];
                    if($post_data['type'] == MediaService::VIDEO){
                        $params['title'] = $file->getUploadName();
                        $params['desc'] = $file->getUploadName();
                    }

                    if(is_string($material = MpService::materialUpload($params))){
                        return $this->error($material);
                    }
                    $material['company_id'] = TenantService::getCompanyId();
                    $material['mp_id'] = $mp_info['id'];
                    $material['title'] = $insert_data['title'];
                    $material['server_url'] = $insert_data['url'];
                    $material['type'] = $post_data['type'];
                    $this->model->create($material);
                    @unlink($dest_name);
                }else{
                    return $this->error($res['msg']);
                }
            }
            return $this->success('上传成功');
        }
    }

    /**
     * 素材列表
     * @param Request $request
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * Author: fudaoji<fdj@kuryun.cn>
     */
    public function index(Request $request){
        $mp_info = $request->mpInfo;
        $types = MpService::materialTypes();
        $type = input('type', MediaService::IMAGE);
        $search_key = input('search_key', '');
        $where = [
            $this->tenantWhere(),
            ['mp_id', '=', $mp_info['id']],
            ['type', '=', $type]
        ];

        $search_key && $where[] = ['title', 'like', '%'.$search_key.'%'];
        $query = $this->model->where($where);
        $type == MediaService::NEWS && $query = $query->where('pid', 0);
        $data_list = $query->order('id', 'desc')
            ->paginate($this->pageSize);
        $pager = $data_list->appends(['type' => $type, 'search_key' => $search_key])->render();
        if($type == MediaService::NEWS){
            foreach ($data_list as $k => $v){
                $where[] = ['pid', '=', $v['id']];
                $v['child'] = $this->model->where($where)
                ->order('index',  'asc')
                ->field(['thumb_url', 'title'])
                ->select();
                $data_list[$k] = $v;
            }
        }
        $assign = [
            'data_list' => $data_list,
            'type' => $type,
            'types' => $types,
            'pager' => $pager,
            'tab_nav' => ['tab_list' => $this->tabList(), 'current_tab' => $type],
            'config' => dao_config('system.upload')
        ];
        return $this->show($assign);
    }

    private function tabList(){
        $types = MpService::materialTypes();
        $list = [];
        foreach ($types as $key => $type){
            $url = in_array($key, [MediaService::TEXT, MediaService::LINK, MediaService::MUSIC]) ? url($key) : url('index', ['type' => $key]);
            $list[$key] = ['title' => $type, 'href' => $url];
        }
        return $list;
    }

    /**
     * 文本
     * @param Request $request
     * @return mixed|\support\Response
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * Author: fudaoji<fdj@kuryun.cn>
     */
    public function text(Request $request)
    {
        $mp_info = $request->mpInfo;
        if (request()->isPost()) {
            $post_data = input('post.');
            $where = [
                ['company_id' ,'=', TenantService::getCompanyId()],
                ['mp_id', '=', $mp_info['id']],
                ['type', '=', MediaService::TEXT]
            ];
            !empty($post_data['search_key']) && $where[] = [
                'content|title', 'like', '%' . $post_data['search_key'] . '%'
            ];
            $query = $this->model->where($where);
            $total = $query->count();
            if ($total) {
                $list = $query->page($post_data['page'], $post_data['limit'])
                    ->order('id', 'desc')
                    ->select();
            } else {
                $list = [];
            }
            return $this->success('success', '', ['total' => $total, 'list' => $list]);
        }

        $builder = new ListBuilder();
        $builder->setTabNav($this->tabList(), __FUNCTION__)
            ->setSearch([
                ['type' => 'text', 'name' => 'search_key', 'title' => '关键词', 'placeholder' => '备注或内容']
            ])
            ->addTopButton('addnew', ['href' => url(__FUNCTION__ . 'Add')])
            ->addTableColumn(['title' => '备注', 'field' => 'title', 'minWidth' => 100])
            ->addTableColumn(['title' => '文本内容', 'field' => 'content', 'minWidth' => 400])
            ->addTableColumn(['title' => '创建时间', 'field' => 'create_time',  'minWidth' => 200])
            ->addTableColumn(['title' => '修改时间', 'field' => 'update_time', 'minWidth' => 200])
            ->addTableColumn(['title' => '操作', 'minWidth' => 120, 'type' => 'toolbar'])
            ->addRightButton('edit', ['href' => url(__FUNCTION__ . 'Edit', ['id' => '__data_id__'])])
            ->addRightButton('delete');

        return $builder->show();
    }

    public function savePost(Request $request, $jump = '', $data = [])
    {
        $data = input('post.');
        $mp_info = $request->mpInfo;
        $data['mp_id'] = $mp_info['id'];
        $data['type'] = input('type');
        switch($data['type']){
            case MediaService::LINK:
                $data['thumb_url'] = $data['thumb_server_url'];
                break;
            case MediaService::MUSIC:
                $data['thumb_url'] = $data['thumb_server_url'];
                $data['server_url'] = $data['voice_server_url'];
                break;
        }
        unset($data['thumb_server_url'],$data['voice_media_id'],$data['voice_server_url']);
        return parent::savePost($request, $jump, $data); // TODO: Change the autogenerated stub
    }

    /**
     * 添加
     * @return mixed
     */
    public function textAdd()
    {
        // 使用FormBuilder快速建立表单页面
        $builder = new FormBuilder();
        $builder->setMetaTitle('新增文本')
            ->setPostUrl(url('savePost', ['type' => MediaService::TEXT]))
            ->addFormItem('title', 'text', '备注', '30字内', [], 'maxlength=30')
            ->addFormItem('content', 'textarea', '文本内容', '1000字内', [], 'required maxlength=10000');

        return $builder->show();
    }

    public function textEdit()
    {
        $id = input('id', null);
        $data = $this->model->where([['id' ,'=', $id], ['company_id','=',TenantService::getCompanyId()]])
            ->find();

        if (!$data) {
            return $this->error('参数错误');
        }

        // 使用FormBuilder快速建立表单页面
        $builder = new FormBuilder();
        $builder->setMetaTitle('编辑文本')
            ->setPostUrl(url('savePost', ['type' => MediaService::TEXT]))
            ->addFormItem('id', 'hidden', 'ID', 'ID')
            ->addFormItem('title', 'text', '备注', '30字内', [], 'maxlength=30')
            ->addFormItem('content', 'textarea', '文本内容', '1000字内', [], 'required maxlength=10000')
            ->setFormData($data);

        return $builder->show();
    }

    /**
     * 链接
     * @param Request $request
     * @return mixed|\support\Response
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * Author: fudaoji<fdj@kuryun.cn>\
     */
    public function link(Request $request)
    {
        $mp_info = $request->mpInfo;
        if (request()->isPost()) {
            $post_data = input('post.');
            $where = [
                ['company_id' ,'=', TenantService::getCompanyId()],
                ['mp_id', '=', $mp_info['id']],
                ['type', '=', MediaService::LINK]
            ];
            !empty($post_data['search_key']) && $where[] = [
                'title|digest', 'like', '%' . $post_data['search_key'] . '%'
            ];
            $query = $this->model->where($where);
            $total = $query->count();
            if ($total) {
                $list = $query->page($post_data['page'], $post_data['limit'])
                    ->order('id', 'desc')
                    ->select();
            } else {
                $list = [];
            }
            return $this->success('success', '', ['total' => $total, 'list' => $list]);
        }

        $builder = new ListBuilder();
        $builder->setTabNav($this->tabList(), __FUNCTION__)
            ->setSearch([
                ['type' => 'text', 'name' => 'search_key', 'title' => '关键词', "placeholder" => '标题、描述']
            ])
            ->addTopButton('addnew', ['href' => url(__FUNCTION__ . 'Add')])
            ->addTableColumn(['title' => '标题', 'field' => 'title', 'minWidth' => 100])
            ->addTableColumn(['title' => '描述', 'field' => 'digest', 'minWidth' => 200])
            ->addTableColumn(['title' => '封面', 'field' => 'thumb_url', 'minWidth' => 100, "type" => 'picture'])
            ->addTableColumn(['title' => '跳转链接', 'field' => 'source_url', 'minWidth' => 200])
            ->addTableColumn(['title' => '创建时间', 'field' => 'create_time', 'minWidth' => 180])
            ->addTableColumn(['title' => '修改时间', 'field' => 'update_time',  'minWidth' => 180])
            ->addTableColumn(['title' => '操作', 'minWidth' => 120, 'type' => 'toolbar'])
            ->addRightButton('edit', ['href' => url(__FUNCTION__ . 'Edit', ['id' => '__data_id__'])])
            ->addRightButton('delete');

        return $builder->show();
    }

    /**
     * 添加
     * @return mixed
     */
    public function linkAdd()
    {
        // 使用FormBuilder快速建立表单页面
        $builder = new FormBuilder();
        $builder->setMetaTitle('新增分享链接')
            ->setPostUrl(url('savePost', ['type' => MediaService::LINK]))
            ->addFormItem('title', 'text', '标题', '100字内', [], 'required maxlength=150')
            ->addFormItem('digest', 'textarea', '描述', '200字内', [], 'required maxlength=200')
            ->addFormItem('thumb', 'choose_picture', '选择图片', '图片比例1:1', [], 'required')
            ->addFormItem('source_url', 'text', '跳转链接', '跳转链接', [], 'required');

        return $builder->show();
    }

    public function linkEdit()
    {
        $id = input('id', 0);
        $data = $this->model->where([['id' ,'=', $id], ['company_id','=', TenantService::getCompanyId()]])
            ->find();

        if (!$data) {
            return $this->error('参数错误');
        }

        $data['thumb'] = [
            'server_url' => $data['thumb_url'],
            'media_id' => $data['thumb_media_id']
        ];

        // 使用FormBuilder快速建立表单页面
        $builder = new FormBuilder();
        $builder->setMetaTitle('编辑分享链接')
            ->setPostUrl(url('savePost', ['type' => MediaService::LINK]))
            ->addFormItem('id', 'hidden', 'ID', 'ID')
            ->addFormItem('title', 'text', '标题', '100字内', [], 'required maxlength=100')
            ->addFormItem('digest', 'textarea', '描述', '200字内', [], 'required maxlength=200')
            ->addFormItem('thumb', 'choose_picture', '选择图片', '图片比例1:1', [], 'required')
            ->addFormItem('source_url', 'text', '跳转链接', '跳转链接', [], 'required')
            ->setFormData($data);

        return $builder->show();
    }

    /**
     * 音乐
     * @param Request $request
     * @return mixed|\support\Response
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * Author: fudaoji<fdj@kuryun.cn>\
     */
    public function music(Request $request)
    {
        $mp_info = $request->mpInfo;
        if (request()->isPost()) {
            $post_data = input('post.');
            $where = [
                ['company_id' ,'=', TenantService::getCompanyId()],
                ['mp_id', '=', $mp_info['id']],
                ['type', '=', MediaService::MUSIC]
            ];
            !empty($post_data['search_key']) && $where[] = [
                'title|digest', 'like', '%' . $post_data['search_key'] . '%'
            ];
            $query = $this->model->where($where);
            $total = $query->count();
            if ($total) {
                $list = $query->page($post_data['page'], $post_data['limit'])
                    ->order('id', 'desc')
                    ->select();
            } else {
                $list = [];
            }
            return $this->success('success', '', ['total' => $total, 'list' => $list]);
        }

        $builder = new ListBuilder();
        $builder->setTabNav($this->tabList(), __FUNCTION__)
            ->setSearch([
                ['type' => 'text', 'name' => 'search_key', 'title' => '关键词', "placeholder" => '标题、描述']
            ])
            ->addTopButton('addnew', ['href' => url(__FUNCTION__ . 'Add')])
            ->addTableColumn(['title' => '标题', 'field' => 'title', 'minWidth' => 100])
            ->addTableColumn(['title' => '描述', 'field' => 'digest', 'minWidth' => 200])
            ->addTableColumn(['title' => '封面', 'field' => 'thumb_url', 'minWidth' => 100, "type" => 'picture'])
            ->addTableColumn(['title' => '音乐链接', 'field' => 'server_url', "type" => 'voice', 'minWidth' => 200])
            ->addTableColumn(['title' => '创建时间', 'field' => 'create_time', 'minWidth' => 180])
            ->addTableColumn(['title' => '修改时间', 'field' => 'update_time',  'minWidth' => 180])
            ->addTableColumn(['title' => '操作', 'minWidth' => 120, 'type' => 'toolbar'])
            ->addRightButton('edit', ['href' => url(__FUNCTION__ . 'Edit', ['id' => '__data_id__'])])
            ->addRightButton('delete');

        return $builder->show();
    }

    /**
     * 添加
     * @return mixed
     */
    public function musicAdd()
    {
        // 使用FormBuilder快速建立表单页面
        $builder = new FormBuilder();
        $builder->setMetaTitle('新增音乐')
            ->setPostUrl(url('savePost', ['type' => MediaService::MUSIC]))
            ->addFormItem('title', 'text', '标题', '100字内', [], 'required maxlength=150')
            ->addFormItem('digest', 'textarea', '描述', '200字内', [], 'required maxlength=200')
            ->addFormItem('thumb', 'choose_picture', '选择图片', '图片比例1:1', [], 'required')
            ->addFormItem('voice', 'choose_voice', '上传音乐', '填写音乐链接或者选择上传的音频文件，常用格式：mp3', [], 'required')
            ->addFormItem('source_url', 'text', '跳转链接', '没有高品质音乐链接，请留空。高质量音乐链接，WIFI环境优先使用该链接播放音乐');

        return $builder->show();
    }

    public function musicEdit()
    {
        $id = input('id', 0);
        $data = $this->model->where([['id' ,'=', $id], ['company_id','=', TenantService::getCompanyId()]])
            ->find();

        if (!$data) {
            return $this->error('参数错误');
        }
        $data['voice'] = [
            'server_url' => $data['server_url'],
            'media_id' => $data['media_id']
        ];

        // 使用FormBuilder快速建立表单页面
        $builder = new FormBuilder();
        $builder->setMetaTitle('编辑音乐')
            ->setPostUrl(url('savePost', ['type' => MediaService::MUSIC]))
            ->addFormItem('id', 'hidden', 'ID', 'ID')
            ->addFormItem('title', 'text', '标题', '100字内', [], 'required maxlength=100')
            ->addFormItem('digest', 'textarea', '描述', '200字内', [], 'required maxlength=200')
            ->addFormItem('thumb', 'choose_picture', '选择图片', '图片比例1:1', [], 'required')
            ->addFormItem('voice', 'choose_voice', '上传音乐', '填写音乐链接或者选择上传的音频文件，常用格式：mp3', [], 'required')
            ->addFormItem('source_url', 'text', '跳转链接', '没有高品质音乐链接，请留空。高质量音乐链接，WIFI环境优先使用该链接播放音乐')
            ->setFormData($data);

        return $builder->show();
    }
}